/*(c)http://gitee.com/silis/PromiseJS*/

(function(win){
	if(window.top.Promise && window.top.Promise.agent == "silis") return win.Promise = win.top.Promise;

	var promiseThenService_InvokeResolve = function(promise, result){
		if(promise.state == "pending"){
			if(result instanceof Promise){
				result.then(function(result2){
					promise.state = "fulfilled";
					promise.value = result2;
					for(var i = 0; i < promise.thens.length; i++){
						promise.thens[i][0](result2);
					}
					promise.thens = null;
				});
			} else {
				promise.state = "fulfilled";
				promise.value = result;
				for(var i = 0; i < promise.thens.length; i++){
					promise.thens[i][0](result);
				}
				promise.thens = null;
			}
		}
	};

	var promiseThenService_InvokeReject = function(promise, error){
		if(promise.state == "pending"){
			promise.state = "rejected";
			promise.error = error;
			for(var i = 0; i < promise.thens.length; i++){
				promise.thens[i][1](error);
			}
			promise.thens = null;
		}

		setTimeout(function(){
			if(!promise.errored) console.error(error);
		},0);
	};

	var Promise = win.Promise = function(fn){
		var promise = this;
		promise.state = "pending";

		promise.thens = [];


		try{
			fn(function(result){
				promiseThenService_InvokeResolve(promise, result);
			}, function(error){
				promiseThenService_InvokeReject(promise, error);
			})
		}catch(error){
			promiseThenService_InvokeReject(promise, error);
		}
	};

	Promise.prototype = {
		then:function(resolve, reject){ var promise = this;
			if(!resolve) resolve = function(){};
			if(!reject) reject = function(){}; else {
				//报错时设置已处理错误状态
				var sourceReject = reject;
				reject = function(error){
					promise.errored = true;
					sourceReject(error);
				}
			};
			var nextPromise = new Promise(function(){});

			var item = [function(result){
				try{
					result = resolve(result);
					
					promiseThenService_InvokeResolve(nextPromise, result);
				}catch(error){
					promiseThenService_InvokeReject(nextPromise, error);
				}
			}, function(error){
				reject(error);
				promiseThenService_InvokeReject(nextPromise, error);
			}];
			
			switch(promise.state){
				case "pending":
					promise.thens.push(item);
					break;
				case "fulfilled":
					item[0](promise.value);
					break;
				case "rejected":
					item[1](promise.error);
					break;
			}

			return nextPromise;
		},
	}

	Promise.all = function(arr){
		arr = arr.slice();
		var count = 0, results = [];
		return new Promise(function(resolve, reject){
			if(arr.length == 0){
				resolve(results);
			} else {
				arr.forEach(function(item, index){
					item.then(function(result){
						results[index] = result;
						count++;
						if(count >= arr.length) resolve(results);
					}, function(error){
						reject(error);
					});
				});
			};
		});
	}

	Promise.resolve = function(result){
		return new Promise(function(resolve, reject){
			return resolve(result);
		});
	}

	Promise.reject = function(error){
		return new Promise(function(resolve, reject){
			return reject(error);
		});
	}

	Promise.agent = "silis";


})(window);